﻿// --------------------------------------------------------------------------------------------------------------------
// <copyright file="BaseUseCaseEngine.cs" company="">
//   
// </copyright>
// <summary>
//   The base use case engine.
// </summary>
// --------------------------------------------------------------------------------------------------------------------

namespace Libium.UseCases
{
    using System;
    using System.Collections.Generic;
    using System.IO;

    using Libium.Bindings;

    /// <summary>
    ///   The base use case engine.
    /// </summary>
    public class BaseUseCaseEngine : IUseCaseEngine, IUseCaseInstanceService
    {
        #region Fields

        /// <summary>
        ///   The _bind service.
        /// </summary>
        private CompoundBindService _bindService;

        #endregion

        #region Explicit Interface Properties

        /// <summary>
        ///   Gets the temporary file path.
        /// </summary>
        string IUseCaseInstanceService.TemporaryFilePath
        {
            get
            {
                return Path.GetTempPath();
            }
        }

        #endregion

        #region Public Methods and Operators

        /// <summary>
        /// The execute modal use case.
        /// </summary>
        /// <param name="useCase">
        /// The use case. 
        /// </param>
        /// <returns>
        /// The <see cref="CommandDefinition"/> . 
        /// </returns>
        public virtual CommandDefinition ExecuteModalUseCase(IUseCase useCase)
        {
            var view = CreateViewForUseCase(useCase);
            Bind(useCase, view);
            ShowViewModal(view);
            return null;
        }

        /// <summary>
        /// The execute use case.
        /// </summary>
        /// <param name="useCase">
        /// The use case. 
        /// </param>
        public virtual void ExecuteUseCase(IUseCase useCase)
        {
            var view = CreateViewForUseCase(useCase);
            Bind(useCase, view);
            ShowViewModal(view);
        }

        /// <summary>
        ///   The get service.
        /// </summary>
        /// <typeparam name="T"> </typeparam>
        /// <returns> The <see cref="T" /> . </returns>
        /// <exception cref="NotImplementedException"></exception>
        public virtual T GetService<T>()
        {
            throw new NotImplementedException();
        }

        #endregion

        #region Explicit Interface Methods

        /// <summary>
        ///   The create use case.
        /// </summary>
        /// <typeparam name="T"> </typeparam>
        /// <returns> The <see cref="T" /> . </returns>
        T IUseCaseInstanceService.CreateUseCase<T>()
        {
            IUseCase useCase = null;
            if (typeof(T) == typeof(IOpenFileUseCase))
            {
                useCase = new OpenFileUseCase(null, this);
            }
            else if (typeof(T) == typeof(ISaveFileUseCase))
            {
                useCase = new SaveFileUseCase(null, this);
            }

            return (T)useCase;
        }

        /// <summary>
        /// The execute command.
        /// </summary>
        /// <param name="command">
        /// The command. 
        /// </param>
        void IUseCaseInstanceService.ExecuteCommand(ICommand command)
        {
            var useCases = new List<IUseCase>();

            var useCase = command.UseCase;
            while (useCase != null)
            {
                useCases.Insert(0, useCase);
                useCase = useCase.Parent;
            }

            // var useCase = command.UseCase as ICompoundUseCase;
            // if (useCase != null)
            // {
            // 	useCase = useCase.ActiveUseCase;
            // 	while (useCase != null)
            // 	{
            // 		useCases.Add(useCase);
            // 		useCase = useCase.ActiveUseCase;
            // 	}
            // }
            var tonnelCall = new CommandCall(command, CommandHandlePhase.Tonnel);
            for (var index = 0; index < useCases.Count; index++)
            {
                useCase = useCases[index];
                useCase.ExecuteCommand(tonnelCall);
                if (tonnelCall.Handled)
                {
                    return;
                }
            }

            var bubbleCall = new CommandCall(command, CommandHandlePhase.Bubble);
            for (var index = useCases.Count - 1; index >= 0; index--)
            {
                useCase = useCases[index];
                useCase.ExecuteCommand(bubbleCall);
                if (bubbleCall.Handled)
                {
                    return;
                }
            }
        }

        #endregion

        #region Methods

        /// <summary>
        /// The bind.
        /// </summary>
        /// <param name="useCase">
        /// The use case. 
        /// </param>
        /// <param name="view">
        /// The view. 
        /// </param>
        protected virtual void Bind(IUseCase useCase, object view)
        {
            var bindService = GetBindService();
            bindService.Bind(useCase, view);
        }

        /// <summary>
        /// The create view for use case.
        /// </summary>
        /// <param name="useCase">
        /// The use case. 
        /// </param>
        /// <returns>
        /// The <see cref="object"/> . 
        /// </returns>
        /// <exception cref="NotImplementedException">
        /// </exception>
        protected virtual object CreateViewForUseCase(IUseCase useCase)
        {
            throw new NotImplementedException();
        }

        /// <summary>
        ///   The get bind service.
        /// </summary>
        /// <returns> The <see cref="CompoundBindService" /> . </returns>
        protected CompoundBindService GetBindService()
        {
            if (_bindService == null)
            {
                _bindService = new CompoundBindService();
                InitializeBindService(_bindService);
            }

            return _bindService;
        }

        /// <summary>
        /// The initialize bind service.
        /// </summary>
        /// <param name="bindService">
        /// The bind service. 
        /// </param>
        protected virtual void InitializeBindService(CompoundBindService bindService)
        {
            var useCaseBindService = new UseCaseBindService { AutoBind = true };
            _bindService.AddBindService(useCaseBindService);
        }

        /// <summary>
        /// The show view modal.
        /// </summary>
        /// <param name="view">
        /// The view. 
        /// </param>
        /// <exception cref="NotImplementedException">
        /// </exception>
        protected virtual void ShowViewModal(object view)
        {
            throw new NotImplementedException();
        }

        #endregion
    }
}